package com.swak.vertx.protocol.http.chain;

import java.util.Map;
import java.util.concurrent.CompletionStage;

import com.swak.utils.Maps;
import com.swak.vertx.protocol.http.adapter.Adapter;
import com.swak.vertx.protocol.http.adapter.Adapter.Context;

/**
 * 执行链
 * 
 * @author lifeng
 */
@FunctionalInterface
public interface Chain {

	/**
	 * 不需要
	 */
	Chain NONE = NoneChain.INSTANCE;

	/**
	 * 执行责任链
	 * 
	 * @param context
	 * @return
	 */
	CompletionStage<Context> doChain(Context context);

	public static Map<Integer, Chain> chainCache = Maps.newConcurrentMap();

	public static Chain chain(int id, Adapter[] adapters) {
		if (adapters == null || adapters.length == 0) {
			if (chainCache.containsKey(0)) {
				return chainCache.get(0);
			}
			return NoneChain.INSTANCE;
		}
		if (chainCache.containsKey(id)) {
			return chainCache.get(id);
		}
		return chainCache.computeIfAbsent(id, (key) -> {
			return chain(adapters);
		});
	}

	static Chain chain(Adapter[] adapters) {
		Adapter first = adapters[0];
		for (int i = 0; i < adapters.length - 1; i++) {
			if (adapters[i] == null) {
				break;
			}
			adapters[i].chain(adapters[i + 1]);
		}
		return chainCache.computeIfAbsent(0, (key) -> {
			return (c) -> first.handle(c);
		});
	}
}
